/*
** Copyright (c) 2010 by Lorimark Solutions, LLC.
** All Rights Reserved.
** Send inquiries to: info@lorimarksolutions.com
**
*/
#nolist
/*

    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777
    0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
   +--------------------------------------------------------------------------------------------------------------------------------+
000|                                                                                                                                |
 01|                                                                                                                                |
 02|                                                                                                                                |
 03|                                                                                                                                |
 04|                                                                                                                                |
 05|                                                                                                                                |
 06|                                                                                                                                |
 07|                                                                                                                                |
108|                                                                                                                                |
 09|                                                                                                                                |
 0A|                                                                                                                                |
 0B|                                                                                                                                |
 0C|                                                                                                                                |
 0D|                                                                                                                                |
 0E|                                                                                                                                |
 0F|                                                                                                                                |
210|
 11|
 12| *  *** *** *   *** *** *** *** ***
 13|**    *   * * * *   *     * * * * *
 14| *  ***  ** *** *** ***   *  *  ***
 15| *  *     *   *   * * *   * * *   *
 16|*** *** ***   * *** ***   * ***   *
 17|******************************************************************************************************************************* |
318|                                                                                                                                |
 19|***                                                             *** ***                                     *** *** *** *** *** |
 1A|*** ***                                 ***             *** *** *** *** ***                 *** *** *** *** *** *** *** *** *** |
 1B|*** *** *** *** ***         *** *** *** *** ***         *** *** *** *** *** ***         *** *** *** *** *** *** *** *** *** *** |
 1C|*** *** *** *** ***         *** *** *** *** ***     *** *** *** *** *** *** ***         *** *** *** *** *** *** *** *** *** *** |
 1D|*** *** *** *** *** ***     *** *** *** *** ***     *** *** *** *** *** *** ***     *** *** *** *** *** *** *** *** *** *** *** |
 1E|*** *** *** *** *** ***     *** *** *** *** ***     *** *** *** *** *** *** ***     *** *** *** *** *** *** *** *** *** *** *** |
 1F|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***     *** *** *** *** *** *** *** *** *** *** *** |
420|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 21|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 22|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 23|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 24|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 25|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 26|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 27|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
528|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 29|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2A|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2B|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2C|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2D|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2E|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 2F|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
630|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 31|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 32|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 33|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 34|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 35|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 36|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 37|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
738|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 39|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3A|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3B|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3C|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3D|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3E|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
 3F|*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
   +--------------------------------------------------------------------------------------------------------------------------------+
    00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777
    0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
    00000000000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111111111111111111111111111
     0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1   1
     0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F

reading: subtract 400, divide by 10


*/
#list

#include <pic16F876.h>

#fuses HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP,NOCPD

#use delay(clock=20000000)


//
// Use this port for regular communication on the network
//
#use rs232( baud=19200, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK )
#list

/*
** Load up the interrupt driven serial interface code.
**
*/
#define RX_USART_BUFFER_SIZE    0x01c
#define RX_USART_BUFFER_ADDRESS 0x190
#define TX_USART_BUFFER_SIZE    0x01c
#define TX_USART_BUFFER_ADDRESS 0x1b0
#include <usartio.c>

/*
** Fetch the crc module
**
*/
#include <crc8.c>

/*
** Fetch the font library
**
*/
#include <font3x5.c>

int8 x;
int8 y;
int8 rxch;

int16 batteries[32];
int16 battery;
#locate battery   = 0x110
#locate batteries = 0x112

#list

//*****************************************************************

#bit GLCD_RST = PORTA.0
#bit GLCD_CS2 = PORTA.1
#bit GLCD_CS1 = PORTA.2
#bit GLCD_E   = PORTA.3
#bit GLCD_RW  = PORTA.4
#bit GLCD_DI  = PORTA.5

// ******************************************************************

#bit TRS_TOUCH = TRISC.3
#bit PIN_TOUCH = PORTC.3
#bit TOUCH_PIN = PORTC.2


/*!
** \brief Select a Chip
**
** Since most everything is zero-based in C and in nearly
**  all other systems, I have written this chip selector
**  to be zero-based also.  Sending a chip==0 selects the
**  first chip, sending a chip==1 selects the second chip.
**  Sending anything else selects no chip.
**
**
*/
void chipSelect_lcd( int8 chip )
{
  GLCD_CS1 = 0;
  GLCD_CS2 = 0;
  if( chip == 0 ) GLCD_CS1 = 1;
  if( chip == 1 ) GLCD_CS2 = 1;
  delay_us(5);
}

// Purpose:       Reads a byte of data from the specified chip
// Ouputs:        A byte of data read from the chip
int8 readByte_lcd( int8 chip )
{
   int8 data;        // Stores the data read from the LCD
   chipSelect_lcd(chip);

   port_b_pullups(TRUE);
   TRISB = 0xff;
   GLCD_RW = 1;      // Set for reading
   delay_us(5);
   GLCD_E  = 1;      // Pulse the enable pin
   delay_us(5);
   GLCD_E = 0;
   delay_us(5);
   GLCD_E = 1;       // Pulse the enable pin
   delay_us(5);
   data = PORTB;     // Get the data from the display's output register
   GLCD_E = 0;

   chipSelect_lcd(-1);

   return data;      // Return the read data
}

void busy_lcd( int8 chip )
{
  int8 status = 0x80;
  GLCD_E = 0;
  chipSelect_lcd(chip);
  port_b_pullups(TRUE);
  TRISB = 0xff;
  GLCD_DI = 0;            // Set for instruction
  GLCD_RW = 1;
  while( status == 0x80 )
  {
    delay_us(5);
    GLCD_E = 1;
    delay_us(5);
    status = PORTB;
    delay_us(5);
    GLCD_E = 0;
  }
}

// Purpose:       Write a byte of data to the specified chip
// Inputs:        chipSelect - which chip to write the data to
//                data - the byte of data to write
void writeByte_lcd( int8 chip, int8 data )
{
//  busy_lcd(chip);

  chipSelect_lcd(chip);

  GLCD_E = 1;       // Pulse the enable pin
  GLCD_RW = 0;      // Set for writing
  TRISB = 0x00;
  PORTB = data;     // Put the data on the port
  delay_us(5);
  GLCD_E = 1;       // Pulse the enable pin
  delay_us(5);
  GLCD_E = 0;

  chipSelect_lcd(-1);
}

// Purpose: // Purpose:       Fill the LCD screen with the passed in color.
//                Works much faster than drawing a rectangle to fill the screen.
// Inputs:        ON - turn all the pixels on
//                OFF - turn all the pixels off
// Dependencies:  glcd_writeByte()
void fillScreen_lcd(int8 fillByte)
{
  int8 i, j, x;

  // Loop through the vertical pages
  for( i = 0; i < 8; i++ )
  {
    GLCD_DI = 0;            // Set for instruction
    x = 0b10111000 + i;
    writeByte_lcd( 0,     0b01000000     );  // Set horizontal address to 0
    writeByte_lcd( 1,     0b01000000     );
    writeByte_lcd( 0, x );  // Set page address
    writeByte_lcd( 1, x );
    GLCD_DI = 1;            // Set for data

    //
    // Loop through the horizontal sections
    //
    for( j = 0; j < 64; j++ )
    {
       writeByte_lcd( 0, fillByte );  // Turn pixels on or off
       writeByte_lcd( 1, fillByte );  // Turn pixels on or off

//       fillByte++;
    }
  }
}

int8 lcd_x; // 0..127
int8 lcd_y; // 0..63

void add_lcd_x( unsigned char x, unsigned char y )
{
  lcd_x += x;
  if( lcd_x > 127 )
  {
    lcd_x  = 0;
    lcd_y += y;
    if( lcd_y > 63 )
    {
      lcd_y = 0;
    }
  }
}

//      Initialize a graphic LCD. This must be called before any
//                other glcd function is used.
// Inputs:        The initialization mode
//                OFF - Turns the LCD off
//                ON  - Turns the LCD on
// Date:          5/28/2003
void init_lcd(int8 mode)
{
//   ADCON1 = 0x06;
   TRISA  = 0x00;
   TRISB  = 0x00;

   lcd_x = 0;
   lcd_y = 0;

   // Initialze some pins
   GLCD_RST = 0;
   delay_ms(1);
   GLCD_RST = 1;
   GLCD_E   = 0;
   GLCD_CS1 = 0;
   GLCD_CS2 = 0;

   GLCD_DI  = 0;                 // Set for instruction
   writeByte_lcd( 0, 0xC0 );     // Specify first RAM line at the top
   writeByte_lcd( 1, 0xC0 );     //   of the screen
   writeByte_lcd( 0, 0x40 );     // Set the column address to 0
   writeByte_lcd( 1, 0x40 );
   writeByte_lcd( 0, 0xB8 );     // Set the page address to 0
   writeByte_lcd( 1, 0xB8 );
   if( mode == 1 )
   {
      writeByte_lcd( 0, 0x3F );  // Turn the display on
      writeByte_lcd( 1, 0x3F );
   }
   else
   {
      writeByte_lcd( 0, 0x3E );  // Turn the display off
      writeByte_lcd( 1, 0x3E );
   }

   fillScreen_lcd(0);            // Clear the display
}


// Purpose:       Turn a pixel on a graphic LCD on or off
// Inputs:        x - the x coordinate of the pixel
//                y - the y coordinate of the pixel
//                color - ON or OFF
// Output:        1 if coordinate out of range, 0 if in range
void pixel_lcd( int8 x, int8 y, int1 color )
{
  int8 data;
  int8 chip = 0;  // Stores which chip to use on the LCD

  x &= 0b01111111;
  y &= 0b00111111;

  if(x > 63)      // Check for first or second display area
  {
     x   -= 64;
     chip = 1;
  }

  GLCD_DI = 0;       // Set for instruction
  bit_clear(x,7);    // Clear the MSB. Part of an instruction code
  bit_set(x,6);      // Set bit 6. Also part of an instruction code

  writeByte_lcd( chip, x );                                 // Set the horizontal address
  writeByte_lcd( chip, ((y/8) & 0b10111111) | 0b10111000 );   // Set the vertical page address

  GLCD_DI = 1;       // Set for data

  data = readByte_lcd(chip);

//  printf( "x = %02x, chip = %u, data = %02x ", x, chip, data );

  if( color )
     bit_set(data, y%8);         // Turn the pixel on
  else                           // or
     bit_clear(data, y%8);       // turn the pixel off

//  printf( "data = %02x", data );

  GLCD_DI = 0;                   // Set for instruction

  writeByte_lcd( chip, x );      // Set the horizontal address

  GLCD_DI = 1;                   // Set for data

  writeByte_lcd( chip, data );   // Write the pixel data

}


// Purpose:       Write text on a graphic LCD
// Inputs:        (x,y) - The upper left coordinate of the first letter
//                textptr - A pointer to an array of text to display
//                size - The size of the text: 1 = 5x7, 2 = 10x14, ...
//                color - ON or OFF
void text35_lcd( int8 x, int8 y, int8 c, int1 color )
{
  int8 i, j, k;
  int16 inFont = 0;

//  printf( "\r\ntext35_lcd %u %u %c ", x, y, c );

  /*
  ** Make sure the letter is within range.  If it is we pull
  **  the actual font data from the array
  **
  */
  if( c >= (' '-1) && c <= '~' )
  {
    inFont = font3x5[c-(' '-1)];
  }

//  printf( "if:%lx", inFont );

  for( i = 0, k = 0; i < 3; i++ )
  {
//    printf( "\r\n" );

    for( j = 0; j < 5; j++, k++ )
    {
//      printf( "%d", j );

      if( bit_test(inFont,k) )
      {
//        printf( "*" );
        pixel_lcd( x+i, y+j, 1 );
      }
      else
      {
//        printf( " " );
        pixel_lcd( x+i, y+j, 0 );
      }
    }
  }

}

void putc_lcd( int8 c )
{
//  printf( "\r\nputc_lcd %c", c );

  text35_lcd( lcd_x, lcd_y, c, 1 );

  add_lcd_x(4,6); // advance to the next character position
}


#include "serial.c"

#define PACKET_DATA_SIZE     32
#define PACKET_DATA_LOCATION 0x0a0
#include "packet.c"

#bit NET_RX = PORTC.2

void drawBar( int8 bar, int8 value )
{
  int8 barBit[5];
  int8 i, j, k, x;

  #bit chip = bar.6

  i=5;
  k=0;
  while( i-- )
  {
    j = 8;
    while( j-- )
    {
      if( value > k ) bit_set(   barBit[i], j );
      else            bit_clear( barBit[i], j );
      k++;
    }
  }

  // Loop through the vertical pages
  bar *= 4;
//  bar += 0x20;

  for( i=0; i<5; i++ )
  {
    GLCD_DI = 0;            // Set for instruction
    x = 0b10111000 + i + 3;
    writeByte_lcd( chip, 0b01000000 + (bar&0b00111111) );  // Set horizontal address to 0
    writeByte_lcd( chip, x );  // Set page address
    GLCD_DI = 1;            // Set for data

    //
    // Loop through the horizontal sections
    //
    for( j=0; j<3; j++ )
    {
       writeByte_lcd( chip, barBit[i] );  // Turn pixels on or off
    }
  }
}


#define VOFFSET 350

void showBatteries()
{
  int8 bi; bi = (packet.src - 1) * 4;

  battery = (packet.dat[0]*256) + packet.dat[1];
  battery -= VOFFSET;
  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = (packet.src-1) * 16;
//    lcd_y = 18;
//    printf( putc_lcd, "%04lu", battery );
    drawBar( bi, battery );
  }

  ++bi;
  battery = (packet.dat[2]*256) + packet.dat[3];
  battery -= VOFFSET;
  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 1 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
  }

  ++bi;
  battery = (packet.dat[4]*256) + packet.dat[5];
  battery -= VOFFSET;
  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 2 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
  }

  ++bi;
  battery = (packet.dat[6]*256) + packet.dat[7];
  battery -= VOFFSET;
  battery /= 10;
  if( batteries[bi] != battery )
  {
    batteries[bi] = battery;
//    lcd_x = 3 * 2 * 5 + (bi * 32);
//    lcd_y = 18;
//    printf( putc_lcd, "%02lu", battery );
    drawBar( bi, battery );
  }

}

void zapBatteries()
{
  drawBar( 0, 0 );
  drawBar( 1, 0 );
  drawBar( 2, 0 );
  drawBar( 3, 0 );
}

int1 ProcessNetworkResponse()
{
  int8  i;

  lcd_x = 0;
  lcd_y = 6;

  if( !rxNetworkPacket() ) return( 0 );

  /* * * * * * * * * * * * * * * * * * * * * * *
  ** At this point we have a valid packet and it
  **  is addressed to us.  We can now process the
  **  data in it and do whatever is requested.
  **
  */

  /*
  ** Switch on the command
  **
  */
  switch( packet.cmd )
  {
    /*
    ** This is a command to read out all the data
    **
    */
    case 1:
    {
      showBatteries();
      return(1);
    }
  }

  printf( putc_lcd, "no cmd  " );
  return(0);

}

void WaitForAnswer()
{
  int8 timeout = 25;

  while( !ProcessNetworkResponse() && timeout-- )
  {
    delay_ms(2);
  }
}

void txByte( int8 data )
{
  putchar( data );
  crc8( data );
}

void main()
{
  int8 target;
  int8 i;
  int8 j;
  x = 0;
  y = 0;
  rxch = 0;
  nodeID = 0;

  init_lcd(1);

  txUsartReset();
  rxUsartReset();

  RCIE = 1;
  PEIE = 1;
  GIE  = 1;

  TRISC5 = 0;
  PORTC5 = 0;
  TRISC4 = 0;
  PORTC4 = 0;

  lcd_x = 0;
  lcd_y = 0;
  printf( putc_lcd, "start " );

  printf( "OK" );

  delay_ms(1000);

  while( rxUsartCount() )
  {
    rxch = rxUsartGet();
    printf( putc_lcd, "%c", rxch );
  }

  for( i=0; i<32; i++ )
  {
    batteries[i] = 0xffff;
  }

  for( ;; )
  {

//    delay_ms(1000);

//    if( !--j )
//    {
//      lcd_x = 9*4;
//      lcd_y = 0;
//      printf( putc_lcd, "%u", x++ );
//    }

    for( target=1; target<9; target++ )
    {
      PORTC5 ^= 1;
      crc8Result = 0;
      txByte( ":"        ); // atn
      txByte( target     ); // dst
      txByte( nodeID     ); // src
      txByte( 1          ); // cmd
      txByte( 0          ); // len
      txByte( crc8Result ); // crc

      WaitForAnswer();
    }

//    printf( "\r\n" );

//    printf( "x %02x y %02x c %u ", x, y, c );

//    while( NET_RX )
//      delay_ms(1);

//    fillScreen_lcd(i);

//    text57_lcd( 0, 0, x, 14, 1 );

//    pixel_lcd( x, y, c );

//    x++;
//    x %= 128;
//    if( !x )
//    {
//      y++;
//      y %= 64;
//      if( !y )
//      {
//        c ^= 1;
//      }
//    }

//    fillScreen_lcd(i) = 0;
//    lcd_y = 0;

#ifdef LCD_DISPLAY_TEST
    for( j = ' '; j <= '~'; j++ )
    {
      text35_lcd( lcd_x, lcd_y, ' '-1, 1 );

      delay_ms(200);

      text35_lcd( lcd_x, lcd_y, j, 1 );

      add_lcd_x(4,6); // advance to the next character position

      delay_ms(200);
    }
#endif

//    lcd_x = 0;
//    lcd_y = 6;
//    printf( putc_lcd, "I Value = %02x", i );

//    ProcessNetworkResponse();

//    delay_ms(500);

  }

}

typedef struct
{
  int8 rxData;
  int8 _PCLATH;
  int8 _STAT;
  int8 _FSR;
  int8 _0;
  int8 _78;
  int8 _7a;
} ispSave_t;

ispSave_t ispSave;

int8 w_temp;
#locate w_temp = 0x7f

#int_global
void isp_global()
{
  /*
  ** This will save the processor state
  **
  */
  #asm
    movwf w_temp            // Save the W register
    swapf STATUS,W          // Save the status register
    clrf  STATUS            //
    movwf ispSave._STAT     //
    movf  PCLATH,w          // Save the PCLATH
    movwf ispSave._PCLATH   //
    clrf  PCLATH
    movf  FSR,W             // Save the FSR register
    movwf ispSave._FSR      //

    movf  0x78,w
    movwf ispSave._78
    movf  0x7a,w
    movwf ispSave._7a
  #endasm

//  PORTC5 = 1;

  /*
  ** Perform the USART interrupt service procedure.
  **
  */
  UsartISP();

  /*
  ** Clear the Interrupt Source
  **
  */
  INTCON &= ~7;

  /*
  ** Enable the global interrupts.
  **
  */
  GIE = 1;

  /*
  ** Restore the processor state.
  **
  */
  #asm
     movf  ispSave._78,w
     movwf 0x78
     movf  ispSave._7a,w
     movwf 0x7a

     movf  ispSave._FSR,W     // Restore the FSR register
     movwf FSR                //
     movf  ispSave._PCLATH,W  // Restore the PCLATH
     movwf PCLATH
     swapf ispSave._STAT,W
     movwf STATUS             //
     swapf w_temp
     swapf w_temp,W
  #endasm

}

